/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.core;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import javax.management.ObjectName;

import org.apache.catalina.AccessLog;
import org.apache.catalina.Cluster;
import org.apache.catalina.Container;
import org.apache.catalina.ContainerEvent;
import org.apache.catalina.ContainerListener;
import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Globals;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Loader;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Realm;
import org.apache.catalina.Valve;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.util.ContextName;
import org.apache.catalina.util.LifecycleMBeanBase;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.MultiThrowable;
import org.apache.tomcat.util.res.StringManager;


/**
 * Abstract implementation of the <b>Container</b> interface, providing common
 * functionality required by nearly every implementation.  Classes extending
 * this base class must may implement a replacement for <code>invoke()</code>.
 * <p>
 * All subclasses of this abstract base class will include support for a
 * Pipeline object that defines the processing to be performed for each request
 * received by the <code>invoke()</code> method of this class, utilizing the
 * "Chain of Responsibility" design pattern.  A subclass should encapsulate its
 * own processing functionality as a <code>Valve</code>, and configure this
 * Valve into the pipeline by calling <code>setBasic()</code>.
 * <p>
 * This implementation fires property change events, per the JavaBeans design
 * pattern, for changes in singleton properties.  In addition, it fires the
 * following <code>ContainerEvent</code> events to listeners who register
 * themselves with <code>addContainerListener()</code>:
 * <table border=1>
 *   <caption>ContainerEvents fired by this implementation</caption>
 *   <tr>
 *     <th>Type</th>
 *     <th>Data</th>
 *     <th>Description</th>
 *   </tr>
 *   <tr>
 *     <td><code>addChild</code></td>
 *     <td><code>Container</code></td>
 *     <td>Child container added to this Container.</td>
 *   </tr>
 *   <tr>
 *     <td><code>{@link #getPipeline() pipeline}.addValve</code></td>
 *     <td><code>Valve</code></td>
 *     <td>Valve added to this Container.</td>
 *   </tr>
 *   <tr>
 *     <td><code>removeChild</code></td>
 *     <td><code>Container</code></td>
 *     <td>Child container removed from this Container.</td>
 *   </tr>
 *   <tr>
 *     <td><code>{@link #getPipeline() pipeline}.removeValve</code></td>
 *     <td><code>Valve</code></td>
 *     <td>Valve removed from this Container.</td>
 *   </tr>
 *   <tr>
 *     <td><code>start</code></td>
 *     <td><code>null</code></td>
 *     <td>Container was started.</td>
 *   </tr>
 *   <tr>
 *     <td><code>stop</code></td>
 *     <td><code>null</code></td>
 *     <td>Container was stopped.</td>
 *   </tr>
 * </table>
 * Subclasses that fire additional events should document them in the
 * class comments of the implementation class.
 *
 * @author Craig R. McClanahan
 */
public abstract class ContainerBase extends LifecycleMBeanBase implements Container {

    private static final Log log = LogFactory.getLog(ContainerBase.class);//记录日志对象。

    /**
     * Perform addChild with the permissions of this class.
     * addChild can be called with the XML parser on the stack,
     * this allows the XML parser to have fewer privileges than
     * Tomcat.
     */
    protected class PrivilegedAddChild implements PrivilegedAction<Void> {//添加子容器在XML解析器中执行的，所有的容器层级结构都在server.xml中定义，所以必定是通过解析XML创建层级结构对象，需要使用该类提供对应的权限，当然读者可以忽略它。因为通常不会使用Java安全管理器。

        private final Container child;

        PrivilegedAddChild(Container child) {
            this.child = child;
        }

        @Override
        public Void run() {
            addChildInternal(child);
            return null;
        }

    }


    // ----------------------------------------------------- Instance Variables


    /**
     * The child Containers belonging to this Container, keyed by name.
     */
    protected final HashMap<String, Container> children = new HashMap<>();//存放子容器的HashMap。


    /**
     * The processor delay for this component.
     */
    protected int backgroundProcessorDelay = -1;//容器周期性任务的延迟时间。


    /**
     * The container event listeners for this Container. Implemented as a
     * CopyOnWriteArrayList since listeners may invoke methods to add/remove
     * themselves or other listeners and with a ReadWriteLock that would trigger
     * a deadlock.
     */
    protected final List<ContainerListener> listeners = new CopyOnWriteArrayList<>();//监听器集合，用于监听容器发布的事件。

    /**
     * The Logger implementation with which this Container is associated.
     */
    protected Log logger = null;//与容器联合使用的日志对象。


    /**
     * Associated logger name.
     */
    protected String logName = null;//日志对象名


    /**
     * The cluster with which this Container is associated.
     */
    protected Cluster cluster = null;//与容器联合使用的集群对象。
    private final ReadWriteLock clusterLock = new ReentrantReadWriteLock();//保护集群对象的读写锁。


    /**
     * The human-readable name of this Container.
     */
    protected String name = null;//当前容器名。


    /**
     * The parent Container to which this Container is a child.
     */
    protected Container parent = null;//当前容器的父容器。


    /**
     * The parent class loader to be configured when we install a Loader.
     */
    protected ClassLoader parentClassLoader = null;//当使用Loader组件时，使用的父类加载器。


    /**
     * The Pipeline object with which this Container is associated.
     */
    protected final Pipeline pipeline = new StandardPipeline(this);//与容器联合使用的流水线对象。


    /**
     * The Realm with which this Container is associated.
     */
    private volatile Realm realm = null;//与容器联合使用的Realm对象。


    /**
     * Lock used to control access to the Realm.
     */
    private final ReadWriteLock realmLock = new ReentrantReadWriteLock();//用于保护访问Realm的读写锁。


    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager.getManager(ContainerBase.class);//当前包中的类公用的字符串处理对象。


    /**
     * Will children be started automatically when they are added.
     */
    protected boolean startChildren = true;//用于标识当子组件被添加时自动启动。

    /**
     * The property change support for this component.
     */
    protected final PropertyChangeSupport support =
            new PropertyChangeSupport(this);//用于支持属性修改。


    /**
     * The background thread.
     */
    private Thread thread = null;//后台执行周期性任务的线程。


    /**
     * The background thread completion semaphore.
     */
    private volatile boolean threadDone = false;//用于标识后台周期性任务是否执行完成。


    /**
     * The access log to use for requests normally handled by this container
     * that have been handled earlier in the processing chain.
     */
    protected volatile AccessLog accessLog = null;//记录容器访问日志。
    private volatile boolean accessLogScanComplete = false;//日志扫描完成标识。


    /**
     * The number of threads available to process start and stop events for any
     * children associated with this container.
     */
    private int startStopThreads = 1;//并行启动和停止子容器的线程数。
    protected ThreadPoolExecutor startStopExecutor;//启动和停止子容器的线程池。


    // ------------------------------------------------------------- Properties

    @Override
    public int getStartStopThreads() {
        return startStopThreads;
    }

    /**
     * Handles the special values.
     */
    private int getStartStopThreadsInternal() {//获取最终的并行线程数。
        int result = getStartStopThreads();//获取默认的线程数。

        // Positive values are unchanged
        if (result > 0) {//如果大于0，那么直接返回。
            return result;//也就是说，如果设置了线程数，那就按照设置的为准。
        }

        // Zero == Runtime.getRuntime().availableProcessors()
        // -ve  == Runtime.getRuntime().availableProcessors() + value
        // These two are the same
        result = Runtime.getRuntime().availableProcessors() + result;//否则取CPU核心数减去result的绝对值，保证最少为1。通常可以设置startStopThreads为0，从而让其取CPU核心数减去startStopThreads的并行线程数。
        if (result < 1) {
            result = 1;
        }
        return result;
    }

    @Override
    public void setStartStopThreads(int startStopThreads) {//设置并行线程数并创建线程池。
        this.startStopThreads = startStopThreads;

        // Use local copies to ensure thread safety
        ThreadPoolExecutor executor = startStopExecutor;
        if (executor != null) {
            int newThreads = getStartStopThreadsInternal();
            executor.setMaximumPoolSize(newThreads);
            executor.setCorePoolSize(newThreads);
        }
    }


    /**
     * Get the delay between the invocation of the backgroundProcess method on
     * this container and its children. Child containers will not be invoked
     * if their delay value is not negative (which would mean they are using
     * their own thread). Setting this to a positive value will cause
     * a thread to be spawn. After waiting the specified amount of time,
     * the thread will invoke the executePeriodic method on this container
     * and all its children.
     */
    @Override
    public int getBackgroundProcessorDelay() {
        return backgroundProcessorDelay;
    }


    /**
     * Set the delay between the invocation of the execute method on this
     * container and its children.
     *
     * @param delay The delay in seconds between the invocation of
     *              backgroundProcess methods
     */
    @Override
    public void setBackgroundProcessorDelay(int delay) {
        backgroundProcessorDelay = delay;
    }


    /**
     * Return the Logger for this Container.
     */
    @Override
    public Log getLogger() {
        if (logger != null) {
            return logger;
        }
        logger = LogFactory.getLog(getLogName());
        return logger;
    }


    /**
     * @return the abbreviated name of this container for logging messages
     */
    @Override
    public String getLogName() {

        if (logName != null) {
            return logName;
        }
        String loggerName = null;
        Container current = this;
        while (current != null) {
            String name = current.getName();
            if ((name == null) || (name.equals(""))) {
                name = "/";
            } else if (name.startsWith("##")) {
                name = "/" + name;
            }
            loggerName = "[" + name + "]"
                + ((loggerName != null) ? ("." + loggerName) : "");
            current = current.getParent();
        }
        logName = ContainerBase.class.getName() + "." + loggerName;
        return logName;

    }


    /**
     * Return the Cluster with which this Container is associated.  If there is
     * no associated Cluster, return the Cluster associated with our parent
     * Container (if any); otherwise return <code>null</code>.
     */
    @Override
    public Cluster getCluster() {//通过读写锁访问Cluster，先获取容器自己的Cluster，如果不存在，则获取父容器的Cluster。
        Lock readLock = clusterLock.readLock();
        readLock.lock();
        try {
            if (cluster != null) {
                return cluster;
            }

            if (parent != null) {
                return parent.getCluster();
            }

            return null;
        } finally {
            readLock.unlock();
        }
    }


    /*
     * Provide access to just the cluster component attached to this container.
     */
    protected Cluster getClusterInternal() {//只获取容器自己的Cluster对象，而不从父容器中获取。
        Lock readLock = clusterLock.readLock();
        readLock.lock();
        try {
            return cluster;
        } finally {
            readLock.unlock();
        }
    }


    /**
     * Set the Cluster with which this Container is associated.
     *
     * @param cluster The newly associated Cluster
     */
    @Override
    public void setCluster(Cluster cluster) {//设置当前容器的Cluster对象，替换旧Cluster并停止，然后启动新的Cluster对象。

        Cluster oldCluster = null;
        Lock writeLock = clusterLock.writeLock();//获取写锁。
        writeLock.lock();
        try {
            // Change components if necessary
            oldCluster = this.cluster;
            if (oldCluster == cluster) {//如果对象相同，那么不需要改变，否则设置为新的Cluster对象。
                return;
            }
            this.cluster = cluster;

            // Stop the old component if necessary
            if (getState().isAvailable() && (oldCluster != null) &&
                (oldCluster instanceof Lifecycle)) {//如果替换后的Cluster对象实现了生命周期函数，那么让其进入停止流程。
                try {
                    ((Lifecycle) oldCluster).stop();
                } catch (LifecycleException e) {
                    log.error(sm.getString("containerBase.cluster.stop"), e);
                }
            }

            // Start the new component if necessary
            if (cluster != null) {//如果新的Cluster实现了生命周期函数，那么让其进入开始流程。
                cluster.setContainer(this);
            }

            if (getState().isAvailable() && (cluster != null) &&
                (cluster instanceof Lifecycle)) {
                try {
                    ((Lifecycle) cluster).start();
                } catch (LifecycleException e) {
                    log.error(sm.getString("containerBase.cluster.start"), e);
                }
            }
        } finally {
            writeLock.unlock();//释放写锁。
        }

        // Report this property change to interested listeners
        support.firePropertyChange("cluster", oldCluster, cluster);//通知属性变化监听器当前容器的cluster属性已经改变。
    }


    /**
     * Return a name string (suitable for use by humans) that describes this
     * Container.  Within the set of child containers belonging to a particular
     * parent, Container names must be unique.
     */
    @Override
    public String getName() {
        return name;
    }


    /**
     * Set a name string (suitable for use by humans) that describes this
     * Container.  Within the set of child containers belonging to a particular
     * parent, Container names must be unique.
     *
     * @param name New name of this container
     *
     * @exception IllegalStateException if this Container has already been
     *  added to the children of a parent Container (after which the name
     *  may not be changed)
     */
    @Override
    public void setName(String name) {//设置容器名。
        if (name == null) {
            throw new IllegalArgumentException(sm.getString("containerBase.nullName"));
        }
        String oldName = this.name;
        this.name = name;
        support.firePropertyChange("name", oldName, this.name);//通知属性变化监听器当前容器的name属性已经改变。
    }


    /**
     * Return if children of this container will be started automatically when
     * they are added to this container.
     *
     * @return <code>true</code> if the children will be started
     */
    public boolean getStartChildren() {
        return startChildren;
    }


    /**
     * Set if children of this container will be started automatically when
     * they are added to this container.
     *
     * @param startChildren New value of the startChildren flag
     */
    public void setStartChildren(boolean startChildren) {//设置startChildren标志位。

        boolean oldStartChildren = this.startChildren;
        this.startChildren = startChildren;
        support.firePropertyChange("startChildren", oldStartChildren, this.startChildren);//通知属性变化监听器当前容器的startChildren属性已经改变。
    }


    /**
     * Return the Container for which this Container is a child, if there is
     * one.  If there is no defined parent, return <code>null</code>.
     */
    @Override
    public Container getParent() {
        return parent;
    }


    /**
     * Set the parent Container to which this Container is being added as a
     * child.  This Container may refuse to become attached to the specified
     * Container by throwing an exception.
     *
     * @param container Container to which this Container is being added
     *  as a child
     *
     * @exception IllegalArgumentException if this Container refuses to become
     *  attached to the specified Container
     */
    @Override
    public void setParent(Container container) {//设置父容器。

        Container oldParent = this.parent;
        this.parent = container;
        support.firePropertyChange("parent", oldParent, this.parent);//通知属性变化监听器当前容器的parent属性已经改变。

    }


    /**
     * Return the parent class loader (if any) for this web application.
     * This call is meaningful only <strong>after</strong> a Loader has
     * been configured.
     */
    @Override
    public ClassLoader getParentClassLoader() {//获取父类加载器。如果已经设置了parentClassLoader，那么直接返回，否则尝试从父容器获取，如果父容器也没有定义，那么获取系统类加载器。
        if (parentClassLoader != null) {
            return parentClassLoader;
        }
        if (parent != null) {
            return parent.getParentClassLoader();
        }
        return ClassLoader.getSystemClassLoader();
    }


    /**
     * Set the parent class loader (if any) for this web application.
     * This call is meaningful only <strong>before</strong> a Loader has
     * been configured, and the specified value (if non-null) should be
     * passed as an argument to the class loader constructor.
     *
     *
     * @param parent The new parent class loader
     */
    @Override
    public void setParentClassLoader(ClassLoader parent) {//设置父类加载器。
        ClassLoader oldParentClassLoader = this.parentClassLoader;
        this.parentClassLoader = parent;
        support.firePropertyChange("parentClassLoader", oldParentClassLoader,
                                   this.parentClassLoader);//通知属性变化监听器当前容器的parentClassLoader属性已经改变。

    }


    /**
     * Return the Pipeline object that manages the Valves associated with
     * this Container.
     */
    @Override
    public Pipeline getPipeline() {
        return this.pipeline;
    }


    /**
     * Return the Realm with which this Container is associated.  If there is
     * no associated Realm, return the Realm associated with our parent
     * Container (if any); otherwise return <code>null</code>.
     */
    @Override
    public Realm getRealm() {//先尝试获取自己的Realm组件，如果没有设置，那么获取父容器的Realm组件。

        Lock l = realmLock.readLock();
        l.lock();
        try {
            if (realm != null) {
                return realm;
            }
            if (parent != null) {
                return parent.getRealm();
            }
            return null;
        } finally {
            l.unlock();
        }
    }


    protected Realm getRealmInternal() {//获取自己的Realm组件，不尝试从父类获取。
        Lock l = realmLock.readLock();
        l.lock();
        try {
            return realm;
        } finally {
            l.unlock();
        }
    }

    /**
     * Set the Realm with which this Container is associated.
     *
     * @param realm The newly associated Realm
     */
    @Override
    public void setRealm(Realm realm) {//设置与当前容器一起使用的Realm组件。

        Lock l = realmLock.writeLock();//获取读写锁。
        l.lock();
        try {
            // Change components if necessary
            Realm oldRealm = this.realm;
            if (oldRealm == realm) {
                return;
            }
            this.realm = realm;//替换旧的Realm组件。

            // Stop the old component if necessary
            if (getState().isAvailable() && (oldRealm != null) &&
                (oldRealm instanceof Lifecycle)) {
                try {
                    ((Lifecycle) oldRealm).stop();//停止旧的Realm组件。
                } catch (LifecycleException e) {
                    log.error(sm.getString("containerBase.realm.stop"), e);
                }
            }

            // Start the new component if necessary
            if (realm != null) {
                realm.setContainer(this);
            }
            if (getState().isAvailable() && (realm != null) &&
                (realm instanceof Lifecycle)) {
                try {
                    ((Lifecycle) realm).start();//启动新的Realm组件。
                } catch (LifecycleException e) {
                    log.error(sm.getString("containerBase.realm.start"), e);
                }
            }

            // Report this property change to interested listeners
            support.firePropertyChange("realm", oldRealm, this.realm);//通知属性变化监听器当前容器的realm属性已经改变。
        } finally {
            l.unlock();
        }

    }


    // ------------------------------------------------------ Container Methods


    /**
     * Add a new child Container to those associated with this Container,
     * if supported.  Prior to adding this Container to the set of children,
     * the child's <code>setParent()</code> method must be called, with this
     * Container as an argument.  This method may thrown an
     * <code>IllegalArgumentException</code> if this Container chooses not
     * to be attached to the specified Container, in which case it is not added
     *
     * @param child New child Container to be added
     *
     * @exception IllegalArgumentException if this exception is thrown by
     *  the <code>setParent()</code> method of the child Container
     * @exception IllegalArgumentException if the new child does not have
     *  a name unique from that of existing children of this Container
     * @exception IllegalStateException if this Container does not support
     *  child Containers
     */
    @Override
    public void addChild(Container child) {//添加子容器。
        if (Globals.IS_SECURITY_ENABLED) {
            PrivilegedAction<Void> dp =
                new PrivilegedAddChild(child);
            AccessController.doPrivileged(dp);
        } else {
            addChildInternal(child);
        }
    }

    private void addChildInternal(Container child) {//没有使用Java安全管理器时，通过以下方式添加。有的话就是包装一下，依然通过以下方式添加。

        if (log.isDebugEnabled()) {//记录日志。
            log.debug("Add child " + child + " " + this);
        }

        synchronized(children) {//获取对象锁并添加子容器。
            if (children.get(child.getName()) != null) {
                throw new IllegalArgumentException(
                        sm.getString("containerBase.child.notUnique", child.getName()));
            }
            //关联父子容器关系。
            child.setParent(this);  // May throw IAE
            children.put(child.getName(), child);//添加子容器。保存到Map中。
        }

        // Start child
        // Don't do this inside sync block - start can be a slow process and
        // locking the children object can cause problems elsewhere
        try {
            if ((getState().isAvailable() ||
                    LifecycleState.STARTING_PREP.equals(getState())) &&
                    startChildren) {//如果当前容器处于STARTING_PREP阶段并设置了startChildren标志，那么启动子容器。
                child.start();//启动子容器。
            }
        } catch (LifecycleException e) {
            log.error("ContainerBase.addChild: start: ", e);
            throw new IllegalStateException(sm.getString("containerBase.child.start"), e);
        } finally {
            fireContainerEvent(ADD_CHILD_EVENT, child);//通知容器事件监听器，当前容器添加了子容器。
        }
    }


    /**
     * Add a container event listener to this component.
     *
     * @param listener The listener to add
     */
    @Override
    public void addContainerListener(ContainerListener listener) {
        listeners.add(listener);
    }


    /**
     * Add a property change listener to this component.
     *
     * @param listener The listener to add
     */
    @Override
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        support.addPropertyChangeListener(listener);
    }


    /**
     * Return the child Container, associated with this Container, with
     * the specified name (if any); otherwise, return <code>null</code>
     *
     * @param name Name of the child Container to be retrieved
     */
    @Override
    public Container findChild(String name) {//获取名字为name的子容器。
        if (name == null) {
            return null;
        }
        synchronized (children) {
            return children.get(name);
        }
    }


    /**
     * Return the set of children Containers associated with this Container.
     * If this Container has no children, a zero-length array is returned.
     */
    @Override
    public Container[] findChildren() {//获取当前容器定义的所有子容器。注意：这里获取到的是快照值。
        synchronized (children) {
            Container results[] = new Container[children.size()];
            return children.values().toArray(results);
        }
    }


    /**
     * Return the set of container listeners associated with this Container.
     * If this Container has no registered container listeners, a zero-length
     * array is returned.
     */
    @Override
    public ContainerListener[] findContainerListeners() {//获取所有容器监听器
        ContainerListener[] results =
            new ContainerListener[0];
        return listeners.toArray(results);
    }


    /**
     * Remove an existing child Container from association with this parent
     * Container.
     *
     * @param child Existing child Container to be removed
     */
    @Override
    public void removeChild(Container child) {//移除指定为child的子容器。

        if (child == null) {
            return;
        }

        try {
            if (child.getState().isAvailable()) {//child状态正常，那么让其进入停止流程。
                child.stop();
            }
        } catch (LifecycleException e) {
            log.error(sm.getString("containerBase.child.stop"), e);
        }

        try {
            // child.destroy() may have already been called which would have
            // triggered this call. If that is the case, no need to destroy the
            // child again.
            if (!LifecycleState.DESTROYING.equals(child.getState())) {//子容器还没有进入销毁阶段，那么让其进入。
                child.destroy();
            }
        } catch (LifecycleException e) {
            log.error(sm.getString("containerBase.child.destroy"), e);
        }

        synchronized(children) {
            if (children.get(child.getName()) == null) {
                return;
            }
            children.remove(child.getName());//从子容器表中移除子容器。
        }

        fireContainerEvent(REMOVE_CHILD_EVENT, child);//通知容器事件监听器，当前容器移除了子容器。
    }


    /**
     * Remove a container event listener from this component.
     *
     * @param listener The listener to remove
     */
    @Override
    public void removeContainerListener(ContainerListener listener) {
        listeners.remove(listener);
    }


    /**
     * Remove a property change listener from this component.
     *
     * @param listener The listener to remove
     */
    @Override
    public void removePropertyChangeListener(PropertyChangeListener listener) {

        support.removePropertyChangeListener(listener);

    }


    @Override
    protected void initInternal() throws LifecycleException {//自定义生命周期函数的初始化实现。
        //创建负责子容器启动和停止的线程池。可以看到采用的队列并没有指定数量为无界队列，然后这并无影响，因为我们的子容器数量本身就有限。
        BlockingQueue<Runnable> startStopQueue = new LinkedBlockingQueue<>();//创建一个阻塞队列。无界、链表队列。
        startStopExecutor = new ThreadPoolExecutor(
                getStartStopThreadsInternal(),
                getStartStopThreadsInternal(), 10, TimeUnit.SECONDS,
                startStopQueue,
                new StartStopThreadFactory(getName() + "-startStop-"));//创建启动停止线程池。
        startStopExecutor.allowCoreThreadTimeOut(true);//指定了核心线程也可以超时退出，因为不需要一直保持这个线程对象，毕竟子容器的开始和停止不会一直存在。
        super.initInternal();//调用父类的初始化函数。
    }


    /**
     * Start this component and implement the requirements
     * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
     *
     * @exception LifecycleException if this component detects a fatal error
     *  that prevents this component from being used
     */
    @Override
    protected synchronized void startInternal() throws LifecycleException {//自定义生命周期函数的启动实现。

        // Start our subordinate components, if any
        logger = null;
        getLogger();//获取日志对象组件。
        Cluster cluster = getClusterInternal();
        if (cluster instanceof Lifecycle) {
            ((Lifecycle) cluster).start();//启动当前容器的集群组件。
        }
        Realm realm = getRealmInternal();
        if (realm instanceof Lifecycle) {
            ((Lifecycle) realm).start();//启动当前容器的Realm组件。
        }

        // Start our child containers, if any 启动子容器 如果有的话
        Container children[] = findChildren();
        List<Future<Void>> results = new ArrayList<>();
        //将所有子容器放入线程池中启动。
        for (Container child : children) {
            results.add(startStopExecutor.submit(new StartChild(child)));//将任务提交到线程池中，启动子容器。
        }

        MultiThrowable multiThrowable = null;

        for (Future<Void> result : results) {//等待线程池结果，如果出现异常，那么通过MultiThrowable汇总异常信息。
            try {
                result.get();
            } catch (Throwable e) {
                log.error(sm.getString("containerBase.threadedStartFailed"), e);
                if (multiThrowable == null) {
                    multiThrowable = new MultiThrowable();
                }
                multiThrowable.add(e);
            }

        }
        if (multiThrowable != null) {
            throw new LifecycleException(sm.getString("containerBase.threadedStartFailed"),
                    multiThrowable.getThrowable());
        }

        // Start the Valves in our pipeline (including the basic), if any
        if (pipeline instanceof Lifecycle) {//启动Pipeline组件。
            ((Lifecycle) pipeline).start();
        }

        setState(LifecycleState.STARTING);//将状态修改为STARTING。

        // Start our thread
        threadStart();//启动执行周期性任务的线程。
    }


    /**
     * Stop this component and implement the requirements
     * of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
     *
     * @exception LifecycleException if this component detects a fatal error
     *  that prevents this component from being used
     */
    @Override
    protected synchronized void stopInternal() throws LifecycleException {//自定义生命周期函数的停止实现。

        // Stop our thread
        threadStop();//停止执行周期性任务的线程。

        setState(LifecycleState.STOPPING);//将状态修改为STOPPING。

        // Stop the Valves in our pipeline (including the basic), if any
        if (pipeline instanceof Lifecycle &&
                ((Lifecycle) pipeline).getState().isAvailable()) {
            ((Lifecycle) pipeline).stop();//停止当前容器的Pipeline组件。
        }

        // Stop our child containers, if any
        Container children[] = findChildren();
        List<Future<Void>> results = new ArrayList<>();
        //将所有子容器放入线程池中停止。
        for (Container child : children) {
            results.add(startStopExecutor.submit(new StopChild(child)));
        }

        //等待停止结果并收集异常信息。
        boolean fail = false;
        for (Future<Void> result : results) {
            try {
                result.get();
            } catch (Exception e) {
                log.error(sm.getString("containerBase.threadedStopFailed"), e);
                fail = true;
            }
        }
        if (fail) {
            throw new LifecycleException(
                    sm.getString("containerBase.threadedStopFailed"));
        }

        // Stop our subordinate components, if any
        Realm realm = getRealmInternal();
        if (realm instanceof Lifecycle) {
            ((Lifecycle) realm).stop();//停止当前容器的Realm组件。
        }
        Cluster cluster = getClusterInternal();
        if (cluster instanceof Lifecycle) {
            ((Lifecycle) cluster).stop();// 停止当前容器的集群组件。
        }
    }

    @Override
    protected void destroyInternal() throws LifecycleException {//自定义生命周期函数的销毁实现。

        Realm realm = getRealmInternal();
        if (realm instanceof Lifecycle) {
            ((Lifecycle) realm).destroy();//销毁容器的Realm组件。
        }
        Cluster cluster = getClusterInternal();
        if (cluster instanceof Lifecycle) {
            ((Lifecycle) cluster).destroy();//销毁容器的集群组件。
        }

        // Stop the Valves in our pipeline (including the basic), if any
        if (pipeline instanceof Lifecycle) {
            ((Lifecycle) pipeline).destroy();//销毁当前容器的Pipeline组件。
        }

        // Remove children now this container is being destroyed
        for (Container child : findChildren()) {
            removeChild(child);//移除所有子容器。
        }

        // Required if the child is destroyed directly.
        if (parent != null) {//如果父容器存在，从父容器中移除当前容器。
            parent.removeChild(this);
        }

        // If init fails, this may be null
        if (startStopExecutor != null) {
            startStopExecutor.shutdownNow();//停止线程池。
        }

        super.destroyInternal();//调用父类销毁动作。
    }


    /**
     * Check this container for an access log and if none is found, look to the
     * parent. If there is no parent and still none is found, use the NoOp
     * access log.
     */
    @Override
    public void logAccess(Request request, Response response, long time,
            boolean useDefault) {//记录容器访问日志。

        boolean logged = false;

        //通过AccessLog组件记录。
        if (getAccessLog() != null) {
            getAccessLog().log(request, response, time);
            logged = true;
        }

        //如果父容器存在，调用父容器logAccess根据userDefault和logged决定是否记录日志。
        if (getParent() != null) {
            // No need to use default logger once request/response has been logged
            // once
            getParent().logAccess(request, response, time, (useDefault && !logged));
        }
    }

    @Override
    public AccessLog getAccessLog() {//获取容器的AccessLog组件。

        if (accessLogScanComplete) {//如果accessLogScanComplete为true，即扫描完成，那么直接返回accessLog。
            return accessLog;
        }

        //否则遍历当前的Pipeline组件中的Valve，找到定义的AccessLog组件，然后将其添加到AccessLogAdapter中。
        AccessLogAdapter adapter = null;
        Valve valves[] = getPipeline().getValves();
        for (Valve valve : valves) {
            if (valve instanceof AccessLog) {
                if (adapter == null) {
                    adapter = new AccessLogAdapter((AccessLog) valve);
                } else {
                    adapter.add((AccessLog) valve);
                }
            }
        }
        //设置AccessLog组件为AccessLogAdapter对象。
        if (adapter != null) {
            accessLog = adapter;
        }
        accessLogScanComplete = true;//设置accessLogScanComplete为true。
        return accessLog;
    }

    // ------------------------------------------------------- Pipeline Methods


    /**
     * Convenience method, intended for use by the digester to simplify the
     * process of adding Valves to containers. See
     * {@link Pipeline#addValve(Valve)} for full details. Components other than
     * the digester should use {@link #getPipeline()}.{@link #addValve(Valve)} in case a
     * future implementation provides an alternative method for the digester to
     * use.
     *
     * @param valve Valve to be added
     *
     * @exception IllegalArgumentException if this Container refused to
     *  accept the specified Valve
     * @exception IllegalArgumentException if the specified Valve refuses to be
     *  associated with this Container
     * @exception IllegalStateException if the specified Valve is already
     *  associated with a different Container
     */
    public synchronized void addValve(Valve valve) {

        pipeline.addValve(valve);
    }


    /**
     * Execute a periodic task, such as reloading, etc. This method will be
     * invoked inside the classloading context of this container. Unexpected
     * throwables will be caught and logged.
     */
    @Override
    public void backgroundProcess() {//实现周期性执行任务。

        if (!getState().isAvailable()) {//当前容器状态不可用，那么直接返回。
            return;
        }

        //调用Cluster组件的周期性执行任务。
        Cluster cluster = getClusterInternal();
        if (cluster != null) {
            try {
                cluster.backgroundProcess();
            } catch (Exception e) {
                log.warn(sm.getString("containerBase.backgroundProcess.cluster",
                        cluster), e);
            }
        }
        //调用Realm组件的周期性执行任务。
        Realm realm = getRealmInternal();
        if (realm != null) {
            try {
                realm.backgroundProcess();
            } catch (Exception e) {
                log.warn(sm.getString("containerBase.backgroundProcess.realm", realm), e);
            }
        }
        //循环遍历Pipeline组件中的Valve组件，并调用它们的周期性执行任务。
        Valve current = pipeline.getFirst();
        while (current != null) {
            try {
                current.backgroundProcess();
            } catch (Exception e) {
                log.warn(sm.getString("containerBase.backgroundProcess.valve", current), e);
            }
            current = current.getNext();
        }
        //通知容器事件监听器，当前执行了周期性任务事件。
        fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);//发布周期事件。
    }


    @Override
    public File getCatalinaBase() {//从父容器获取CatalinaBase路径。

        if (parent == null) {
            return null;
        }

        return parent.getCatalinaBase();
    }


    @Override
    public File getCatalinaHome() {//从父容器中获取CatalinaHome路径。

        if (parent == null) {
            return null;
        }

        return parent.getCatalinaHome();
    }


    // ------------------------------------------------------ Protected Methods

    /**
     * Notify all container event listeners that a particular event has
     * occurred for this Container.  The default implementation performs
     * this notification synchronously using the calling thread.
     *
     * @param type Event type
     * @param data Event data
     */
    @Override
    public void fireContainerEvent(String type, Object data) {//通知所有容器事件监听器发生了容器事件。type为类型，data为携带数据。

        if (listeners.size() < 1) {
            return;
        }

        ContainerEvent event = new ContainerEvent(this, type, data);//创建容器事件对象。
        // Note for each uses an iterator internally so this is safe
        for (ContainerListener listener : listeners) {//循环遍历通知。
            listener.containerEvent(event);
        }
    }


    // -------------------- JMX and Registration  --------------------

    @Override
    protected String getDomainInternal() {//从容器中获取当前容器注册到JMX中的Domain信息。

        Container p = this.getParent();
        if (p == null) {
            return null;
        } else {
            return p.getDomain();
        }
    }


    @Override
    public String getMBeanKeyProperties() {//生成当前容器注册到JMX中的key字符串。
        Container c = this;
        StringBuilder keyProperties = new StringBuilder();//通过StringBuilder构建。
        int containerCount = 0;

        // Work up container hierarchy, add a component to the name for
        // each container
        while (!(c instanceof Engine)) {//从当前容器一直遍历到底层容器Engine组件生成key。
            if (c instanceof Wrapper) {//构建servlet名。
                keyProperties.insert(0, ",servlet=");
                keyProperties.insert(9, c.getName());
            } else if (c instanceof Context) {//构建Context名，即Web应用名。
                keyProperties.insert(0, ",context=");
                ContextName cn = new ContextName(c.getName(), false);
                keyProperties.insert(9,cn.getDisplayName());
            } else if (c instanceof Host) {//构建Host虚拟主机名。
                keyProperties.insert(0, ",host=");
                keyProperties.insert(6, c.getName());
            } else if (c == null) {//c为空，表明当前运行在内嵌模式或者单元测试中。
                // May happen in unit testing and/or some embedding scenarios
                keyProperties.append(",container");
                keyProperties.append(containerCount++);
                keyProperties.append("=null");
                break;
            } else {//不应该进入这里。
                // Should never happen...
                keyProperties.append(",container");
                keyProperties.append(containerCount++);
                keyProperties.append('=');
                keyProperties.append(c.getName());
            }
            c = c.getParent();//继续往父容器遍历。
        }
        return keyProperties.toString();
    }

    public ObjectName[] getChildren() {//获取所有子容器的ObjectName对象。
        List<ObjectName> names = new ArrayList<>(children.size());
        for (Container next : children.values()) {
            if (next instanceof ContainerBase) {
                names.add(((ContainerBase)next).getObjectName());
            }
        }
        return names.toArray(new ObjectName[0]);
    }


    // -------------------- Background Thread --------------------

    /**
     * Start the background thread that will periodically check for
     * session timeouts.
     */
    protected void threadStart() {//启动后台运行周期性任务线程。

        if (thread != null) {//已经启动或者不需要运行周期性任务时，直接返回。
            return;
        }
        if (backgroundProcessorDelay <= 0) {//周期性执行时间没有指定，则直接返回。
            return;
        }

        //否则创建守护线程开始执行ContainerBackgroudProcessor对象。
        threadDone = false;
        String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
        thread = new Thread(new ContainerBackgroundProcessor(), threadName);//创建线程。
        thread.setDaemon(true);//设置为守护线程。
        thread.start();//启动线程。

    }


    /**
     * Stop the background thread that is periodically checking for
     * session timeouts.
     */
    protected void threadStop() {//停止后台运行周期性任务线程。

        if (thread == null) {
            return;
        }

        threadDone = true;
        thread.interrupt();//中断线程执行。
        try {
            thread.join();//等待线程执行结束。
        } catch (InterruptedException e) {
            // Ignore
        }

        thread = null;

    }


    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        Container parent = getParent();
        if (parent != null) {
            sb.append(parent.toString());
            sb.append('.');
        }
        sb.append(this.getClass().getSimpleName());
        sb.append('[');
        sb.append(getName());
        sb.append(']');
        return sb.toString();
    }


    // -------------------------------------- ContainerExecuteDelay Inner Class

    /**
     * Private runnable class to invoke the backgroundProcess method
     * of this container and its children after a fixed delay.
     */
    protected class ContainerBackgroundProcessor implements Runnable {//用于包装后台执行周期性任务的线程执行体。

        @Override
        public void run() {
            Throwable t = null;
            String unexpectedDeathMessage = sm.getString(
                    "containerBase.backgroundProcess.unexpectedThreadDeath",
                    Thread.currentThread().getName());
            try {
                while (!threadDone) {//循环执行processChildre方法，直到显式停止。
                    try {
                        Thread.sleep(backgroundProcessorDelay * 1000L);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                    if (!threadDone) {
                        processChildren(ContainerBase.this);
                    }
                }
            } catch (RuntimeException|Error e) {
                t = e;
                throw e;
            } finally {
                if (!threadDone) {
                    log.error(unexpectedDeathMessage, t);
                }
            }
        }

        protected void processChildren(Container container) {//完成容器周期性任务的实现。
            ClassLoader originalClassLoader = null;

            try {
                if (container instanceof Context) {
                    //获取当前Loader组件，如果Loader不存在，那么直接返回。
                    Loader loader = ((Context) container).getLoader();
                    // Loader will be null for FailedContext instances
                    if (loader == null) {
                        return;
                    }

                    // Ensure background processing for Contexts and Wrappers
                    // is performed under the web app's class loader
                    originalClassLoader = ((Context) container).bind(false, null);//确保在当前Loader组件下的Context和Wrapper都被执行完毕。
                }
                container.backgroundProcess();//执行当前容器的backgroundProcess方法。
                //执行所有定义了周期性任务的子容器的周期性任务。
                Container[] children = container.findChildren();
                for (Container child : children) {
                    //子容器没有开启自己的后台执行线程，那么由父容器执行子容器的周期性操作。
                    if (child.getBackgroundProcessorDelay() <= 0) {
                        processChildren(child);
                    }
                }
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                log.error(sm.getString("containerBase.backgroundProcess.error"), t);
            } finally {
                //如果当前容器是Context容器，俺么解绑。
                if (container instanceof Context) {
                    ((Context) container).unbind(false, originalClassLoader);
                }
            }
        }
    }


    // ---------------------------- Inner classes used with start/stop Executor

    private static class StartChild implements Callable<Void> {

        private Container child;

        public StartChild(Container child) {
            this.child = child;
        }

        @Override
        public Void call() throws LifecycleException {
            child.start();//直接调用子容器的生命周期start方法，进入容器的开始流程。
            return null;
        }
    }

    private static class StopChild implements Callable<Void> {

        private Container child;

        public StopChild(Container child) {
            this.child = child;
        }

        @Override
        public Void call() throws LifecycleException {
            if (child.getState().isAvailable()) {
                child.stop();//直接调用子容器的生命周期stop方法，进入容器的停止流程。
            }
            return null;
        }
    }

    private static class StartStopThreadFactory implements ThreadFactory {//用于创建线程池的线程工厂。
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        public StartStopThreadFactory(String namePrefix) {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            this.namePrefix = namePrefix;
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(group, r, namePrefix + threadNumber.getAndIncrement());
            thread.setDaemon(true);//设置为守护线程。
            return thread;
        }
    }
}
